#include "HAL4D13.h"
#include <sys/alt_irq.h>
#include "common.h"
#include <alt_types.h>
static void dma_shared();

void usb_1362_device_0_write(alt_16 addr)
{
    IOWR_ISP_1362_PERIPHERAL_COMMAND(ISP1362_AVALON_SLAVE_0_BASE,addr);

}
void usb_1362_device_8_write(alt_16 addr,alt_16 data)
{
    IOWR_ISP_1362_PERIPHERAL_COMMAND(ISP1362_AVALON_SLAVE_0_BASE,addr);
    IOWR_ISP_1362_PERIPHERAL_8_DATA(ISP1362_AVALON_SLAVE_0_BASE,data);
}
void usb_1362_device_16_write(alt_16 addr,alt_16 data)
{
    IOWR_ISP_1362_PERIPHERAL_COMMAND(ISP1362_AVALON_SLAVE_0_BASE,addr);
    IOWR_ISP_1362_PERIPHERAL_DATA(ISP1362_AVALON_SLAVE_0_BASE,data);
}
void usb_1362_device_32_write(alt_16 addr,alt_32 data)
{
    IOWR_ISP_1362_PERIPHERAL_COMMAND(ISP1362_AVALON_SLAVE_0_BASE,addr);
    IOWR_ISP_1362_PERIPHERAL_DATA(ISP1362_AVALON_SLAVE_0_BASE,(alt_16)(data & 0xffff));
    IOWR_ISP_1362_PERIPHERAL_DATA(ISP1362_AVALON_SLAVE_0_BASE,(alt_16)((data>>16) & 0xffff));    
}
alt_16 usb_1362_device_16_read(alt_16 addr)
{
    alt_16 data;
    IOWR_ISP_1362_PERIPHERAL_COMMAND(ISP1362_AVALON_SLAVE_0_BASE,addr);
    data = IORD_ISP_1362_PERIPHERAL_DATA(ISP1362_AVALON_SLAVE_0_BASE);
    return data;
}
alt_32 usb_1362_device_32_read(alt_16 addr)
{
    alt_32 data = 0;
    IOWR_ISP_1362_PERIPHERAL_COMMAND(ISP1362_AVALON_SLAVE_0_BASE,addr);
    data = IORD_ISP_1362_PERIPHERAL_DATA(ISP1362_AVALON_SLAVE_0_BASE);
    data += (IORD_ISP_1362_PERIPHERAL_DATA(ISP1362_AVALON_SLAVE_0_BASE)<<16);
    return data;
}

void usb_1362_device_init()
{
    int i = 0;
    /* DcEndpointConfiguration init */
        /* ep0 out */
    usb_1362_device_16_write(ISP_1362_DcEndpointConfigration_EP0_OUT_Write_reg,
                                DcEndpointConfiguration_FIFOEN_MSK|
                                DcEndpointConfiguration_FFOSZ_64_MSK);
        /* ep0 in */
    usb_1362_device_16_write(ISP_1362_DcEndpointConfigration_EP0_IN_Write_reg,
                                DcEndpointConfiguration_FIFOEN_MSK|
                                DcEndpointConfiguration_FFOSZ_64_MSK|
                                DcEndpointConfiguration_EPDIR_MSK);
        /* ep1 in 64*/
    usb_1362_device_16_write(ISP_1362_DcEndpointConfigration_EPx_Write_reg(1),
                                DcEndpointConfiguration_FIFOEN_MSK|
                                DcEndpointConfiguration_FFOSZ_64_MSK|
                                DcEndpointConfiguration_EPDIR_MSK);
        /* ep2 out 64*/
    usb_1362_device_16_write(ISP_1362_DcEndpointConfigration_EPx_Write_reg(2),
                                DcEndpointConfiguration_FIFOEN_MSK|
                                DcEndpointConfiguration_FFOSZ_64_MSK);
        /* epx for the other 12 ep */
    for(i = 0 ; i < 12 ; i++)
    {
        usb_1362_device_16_write(ISP_1362_DcEndpointConfigration_EPx_Write_reg(3+i),
                                 DcEndpointConfiguration_FFOSZ_64_MSK);
    }
}
void usb_1362_nios_irq_init()
{
    
}
int usb_1362_device_epx_read(char epx,char *buf)
{
    int dataLength;
    int i;
    short *data;
    if(epx == 0)
        dataLength = usb_1362_device_16_read(ISP_1362_EP0_OUT_Buffer_Read_reg);
    else
        dataLength = usb_1362_device_16_read(ISP_1362_EP0_OUT_Buffer_Read_reg + epx + 1);
#if USB_ENU_DEBUG
//    uartPrintf("ep%d out data length:%d\n",epx,dataLength);
   
#endif
 printf("ep%d out data length:%d\n",epx,dataLength);
    data = buf;
    for(i = 0;i < dataLength;i += 2)
    {
        //data += 1;
        (data)[i>>1] = IORD_ISP_1362_PERIPHERAL_DATA(ISP1362_AVALON_SLAVE_0_BASE);
    }
   

/*
   usb_1362_device_16_write(ISP_1362_DcDMACounter_Write_reg,dataLength);
   usb_1362_device_16_write(ISP_1362_DcDMAConfiguration_Write_reg,
   							DcDMAConfiguration_CNTREN_MSK|
   							DcDMAConfiguration_SHORTP_MSK|
   							DcDMAConfiguration_DMAEN_MSK|
   							
   							(epx<<4)
   							);
   							
   dma_shared((char *)0x00681120,2,ISP1362_AVALON_SLAVE_0_BASE + 8,buf,dataLength>>1,(1<<8));
  */ 

	//clear buffer
	if(epx == 0)
   		 usb_1362_device_0_write(ISP_1362_EP0_OUT_Clear_Buffer_reg);
	else
   		 usb_1362_device_0_write(ISP_1362_EPx_Clear_Buffer_reg(epx));
#if USB_ENU_DEBUG
//	for(i = 0;i < dataLength;i++){
//		uartPrintf("%x",(char)((buf)[i]));
//		printf("%x",(char)((buf)[i]));
//		}
//		uartPrintf("\n");
//		printf("\n");
#endif
    return dataLength;
}
int usb_1362_device_epx_write(char epx,char *buf,int length)
{
    int dataLength;
    int i;
    short data;
    if(epx == 0)
        usb_1362_device_16_write(ISP_1362_EP0_IN_Buffer_Write_reg,(alt_16)length);
    else
        usb_1362_device_16_write(ISP_1362_EPx_Buffer_Write_reg(epx),(alt_16)length);

	dataLength = length;
#if USB_ENU_DEBUG
//    uartPrintf("ep%d in data length:%d\n",epx,dataLength);

#endif
	printf("ep%d in data length:%d\n",epx,dataLength);
    for(i = 0;i < dataLength;i += 2) {
		data = 0x00ff & buf[i];
		data = data | (buf[i+1]<<8);
        //data = buf + i;
         //memcpy(&data,buf + i,2);
         IOWR_ISP_1362_PERIPHERAL_DATA(ISP1362_AVALON_SLAVE_0_BASE,data);
    }
			
	// validate buffer
	if(epx == 0)
    		usb_1362_device_0_write(ISP_1362_EP0_IN_Validate_Buffer_reg);
	else
		usb_1362_device_0_write(ISP_1362_EPx_Validate_Buffer_reg(epx));		
    return dataLength;
}
int usb_1362_epx_transmit(char epx,char *buf,int length)
{
//#if USB_ENU_DEBUG
//uartPrintf("ep%d transmit data length %d\n",epx,length);
//printf("ep%d transmit data length %d\n",epx,length);
//#endif
	usb_1362_device_epx_write(epx,buf,length);
//	disable();
//	usleep(100);
//	enable();
}

int usb_1362_epx_receive(char epx,char *buf)
{
	usb_1362_device_epx_read(epx,buf);
}
void enable(void)
{
//printf("+++++++++\n");
	alt_irq_enable(8); 
	//alt_irq_enable_all();
}
void disable(void)
{
//printf("---------\n");
	alt_irq_disable(8); 
	//alt_irq_disable_all();
}
int usb_1362_LockDevice(int i)
{
	if(i == 0)
		usb_1362_device_16_write(ISP_1362_Unlock_Device_Write_reg,0);
	else if(i == 0xaa37)
		usb_1362_device_16_write(ISP_1362_Unlock_Device_Write_reg,0xaa37);	
	
}


int usb_1362_ep0_stall()
{
	usb_1362_device_0_write(ISP_1362_EP0_OUT_STALL_reg);
	usb_1362_device_0_write(ISP_1362_EP0_IN_STALL_reg);
		
}
int usb_1362_set_address(short address)
{
	usb_1362_device_16_write(ISP_1362_DcAddress_Write_reg,address);
}

void usb_1362_disconnect(void)
{

  printf("disconnect\n");
/*	usb_1362_device_16_write(ISP_1362_DcHardwareConfiguration_Write_reg,
							DcHardwareConfiguration_NOLAZY_MSK|
							0x004|
							DcHardwareConfiguration_CLKRUN_MSK);

							*/
      usb_1362_device_16_write(ISP_1362_DcMode_Write_reg,
	  						//DcMode_SOFTCT_MSK|
	  						DcMode_INTENA_MSK);
}

void USB_1362_connect(void)
{

printf("connect\n");
      usb_1362_device_16_write(ISP_1362_DcMode_Write_reg,
	  						DcMode_SOFTCT_MSK|
	  						DcMode_INTENA_MSK);

}
void usb_1362_epx_stall(epx)
{
	if(epx != 0) 
		usb_1362_device_0_write(ISP_1362_EPx_STALL_reg(epx));
	else{
		usb_1362_device_0_write(ISP_1362_EP0_OUT_STALL_reg);
		usb_1362_device_0_write(ISP_1362_EP0_IN_STALL_reg);
		}
		
}
void usb_1362_epx_unstall(epx)
{
	if(epx != 0) 
		usb_1362_device_0_write(ISP_1362_EPx_UNSTALL_reg(epx));
	else{
		usb_1362_device_0_write(ISP_1362_EP0_OUT_UNSTALL_reg);
		usb_1362_device_0_write(ISP_1362_EP0_IN_UNSTALL_reg);
		}
		
}

int debugShowBuf(char * buf,int len)
{
	int i;
	for(i = 0;i < len;i++)
		printf("%02x\n",buf[i]);
}
